// src/components/RightSidebar.tsx
import React, { useState, useEffect } from "react";
import L from "leaflet";
import * as turf from "@turf/turf";
import type { Feature, Polygon, LineString, Point } from "geojson";
import type { DebugData, MissionType } from "../App"; // 导入 MissionType 和 DebugData 类型
import MappingParams from "./MappingParams";
import ObliqueParams from "./ObliqueParams";
import type { DroneModel } from "./ObliqueParams"; // 导入 DroneModel 类型
import MissionStatsComponent from "./MissionStats";
import type {
  PhotoPoint,
  Waypoint,
  FlightRouteResult,
  MissionStats,
  CameraParams,
  MissionParamsForExport, // 导入新的接口
  ExportParams, // 导入新的接口
} from "./utils";

import {
  generateMappingFlightPath,
  generateObliqueFlightPath,
  CAMERA_SENSOR_WIDTH,
  CAMERA_SENSOR_HEIGHT,
  CAMERA_FOCAL_LENGTH,
  CAMERA_IMAGE_WIDTH_PIXELS,
  CAMERA_IMAGE_HEIGHT_PIXELS,
  generateWaylinesWpml, // 导入新的 KMZ 生成函数
  generateTemplateKml, // 导入新的 KMZ 生成函数
} from "./utils";

import JSZip from "jszip"; // 导入 JSZip

interface RightSidebarProps {
  isOpen: boolean;
  onClose: () => void;
  missionType: MissionType;
  drawnPolygon: L.Polygon | null;
  cameraParams: CameraParams;
  onRouteCalculated: (
    newFlightPath: L.FeatureGroup,
    debugInfo: DebugData | null,
    autoAngle?: number // 传递自动计算的角度
  ) => void;
  flightPathLayer: L.FeatureGroup | null;
  calculatedAutoAngle: number | null; // 新增：从 App 传递过来
  showDebugLayers: boolean; // 新增：调试图层显示状态
  onToggleDebugLayers: () => void; // 新增：切换调试图层函数
  takeoffPoint: L.LatLng | null; // 新增：起飞点
}

const RightSidebar: React.FC<RightSidebarProps> = ({
  isOpen,
  onClose,
  missionType,
  drawnPolygon,
  cameraParams,
  onRouteCalculated,
  flightPathLayer,
  calculatedAutoAngle, // 解构新 prop
  showDebugLayers, // 解构新 prop
  onToggleDebugLayers, // 解构新 prop
  takeoffPoint, // 解构新 prop
}) => {
  // 更新 state 类型以包含 autoAngleEnabled
  const [mappingParams, setMappingParams] = useState<{
    altitude: number;
    gsd: number;
    frontalOverlap: number;
    sideOverlap: number;
    speed: number;
    angle: number;
    autoAngleEnabled: boolean;
  } | null>(null);

  //obliqueParams 状态类型以包含新的智能摆动拍摄参数
  const [obliqueParams, setObliqueParams] = useState<{
    altitude: number;
    gsd: number;
    frontalOverlap: number;
    sideOverlap: number;
    speed: number;
    angle: number;
    tiltAngle: number;
    buffer: number;
    autoAngleEnabled: boolean;
    isSmartObliqueEnabled: boolean; // 是否启用智能摆拍
    droneModel: DroneModel; // 无人机型号
  } | null>(null);
  const [missionStats, setMissionStats] = useState<MissionStats | null>(null);
  // exportData 现在会包含 missionParams
  const [exportData, setExportData] = useState<FlightRouteResult | null>(null);

  // 定义相机参数，从 utils 导入
  const CAMERA_PARAMS: CameraParams = {
    SENSOR_WIDTH: CAMERA_SENSOR_WIDTH,
    SENSOR_HEIGHT: CAMERA_SENSOR_HEIGHT,
    FOCAL_LENGTH: CAMERA_FOCAL_LENGTH,
    IMAGE_WIDTH_PIXELS: CAMERA_IMAGE_WIDTH_PIXELS,
    IMAGE_HEIGHT_PIXELS: CAMERA_IMAGE_HEIGHT_PIXELS,
  };

  const handleCalculateRoute = () => {
    if (!drawnPolygon) {
      alert("请先在地图上绘制飞行区域！");
      return;
    }
    if (!takeoffPoint) {
      // 新增：检查起飞点
      alert("请先设置起飞点！");
      return;
    }

    const polygonGeoJSON =
      drawnPolygon.toGeoJSON() as GeoJSON.Feature<GeoJSON.Polygon>;
    let result: FlightRouteResult = {
      waypoints: [], // 仅包含任务航点
      photoPoints: [],
      stats: { duration: 0, distance: 0, photos: 0, area: 0 },
    };
    let debugInfo: DebugData | null = null;
    let autoCalculatedAngleForDisplay: number | undefined; // 用于传递给 App.tsx

    try {
      if (missionType === "mapping" && mappingParams) {
        let effectiveAngle = mappingParams.angle;
        if (mappingParams.autoAngleEnabled && drawnPolygon) {
          const coords = polygonGeoJSON.geometry.coordinates[0]; // 获取多边形外环坐标
          let longestEdgeLength = 0;
          let calculatedLongestEdgeBearing = 0; // 存储原始的 bearing 角度 [-180, 180]

          if (coords.length >= 2) {
            for (let i = 0; i < coords.length - 1; i++) {
              const p1 = turf.point(coords[i]);
              const p2 = turf.point(coords[i + 1]);
              const edgeLength = turf.distance(p1, p2, { units: "meters" });

              if (edgeLength > longestEdgeLength) {
                longestEdgeLength = edgeLength;
                calculatedLongestEdgeBearing = turf.bearing(p1, p2); // bearing 在 [-180, 180]
              }
            }
          }
          // 将 bearing 角度 [-180, 180] 转换为 UI 期望的 [0, 180] 范围
          // 例如：-10度（西北偏西10度）和10度（东北偏东10度）的航线方向在视觉上可能都是“10度”
          // 这里的 Math.abs() 确保角度在 [0, 180] 范围内，表示线段的朝向
          effectiveAngle = Math.abs(calculatedLongestEdgeBearing);
          autoCalculatedAngleForDisplay = effectiveAngle; // 保存用于显示
        }

        const mappingOutput = generateMappingFlightPath(
          polygonGeoJSON,
          mappingParams.altitude,
          mappingParams.gsd,
          mappingParams.frontalOverlap / 100,
          mappingParams.sideOverlap / 100,
          mappingParams.speed,
          effectiveAngle, // 使用有效角度
          cameraParams,
          takeoffPoint // 起飞点作为参考点
        );
        result = mappingOutput.flightResult;
        debugInfo = mappingOutput.debugInfo;
        result.missionParams = {
          altitude: mappingParams.altitude,
          gsd: mappingParams.gsd,
          frontalOverlap: mappingParams.frontalOverlap,
          sideOverlap: mappingParams.sideOverlap,
          speed: mappingParams.speed,
          angle: effectiveAngle, // 保存有效角度
        };
      } else if (missionType === "oblique" && obliqueParams) {
        // 计算最长边角度 (与建图航拍逻辑相同)
        let effectiveAngle = obliqueParams.angle;
        if (obliqueParams.autoAngleEnabled && drawnPolygon) {
          const coords = polygonGeoJSON.geometry.coordinates[0];
          let longestEdgeLength = 0;
          let calculatedLongestEdgeBearing = 0;

          if (coords.length >= 2) {
            for (let i = 0; i < coords.length - 1; i++) {
              const p1 = turf.point(coords[i]);
              const p2 = turf.point(coords[i + 1]);
              const edgeLength = turf.distance(p1, p2, { units: "meters" });

              if (edgeLength > longestEdgeLength) {
                longestEdgeLength = edgeLength;
                calculatedLongestEdgeBearing = turf.bearing(p1, p2);
              }
            }
          }
          effectiveAngle = Math.abs(calculatedLongestEdgeBearing);
          autoCalculatedAngleForDisplay = effectiveAngle;
        }
        const obliqueOutput = generateObliqueFlightPath(
          polygonGeoJSON,
          obliqueParams.altitude,
          obliqueParams.gsd,
          obliqueParams.frontalOverlap / 100,
          obliqueParams.sideOverlap / 100,
          obliqueParams.speed,
          effectiveAngle, // 使用有效角度
          obliqueParams.tiltAngle,
          obliqueParams.buffer,
          cameraParams,
          takeoffPoint, // 起飞点作为参考点
          obliqueParams.isSmartObliqueEnabled, // 智能摆拍
          obliqueParams.droneModel // 无人机型号
        );

        result = obliqueOutput.flightResult;
        debugInfo = obliqueOutput.debugInfo;
        result.missionParams = {
          altitude: obliqueParams.altitude,
          gsd: obliqueParams.gsd,
          frontalOverlap: obliqueParams.frontalOverlap,
          sideOverlap: obliqueParams.sideOverlap,
          speed: obliqueParams.speed,
          angle: effectiveAngle, // 保存有效角度
          tiltAngle: obliqueParams.tiltAngle,
          buffer: obliqueParams.buffer,
          // 智能摆动拍摄的参数也存储到 missionParams 中，以便后续 KMZ 导出使用
          isSmartObliqueEnabled: obliqueParams.isSmartObliqueEnabled,
          droneModel: obliqueParams.droneModel,
        };
      } else {
        alert("请选择任务类型并设置参数！");
        onRouteCalculated(new L.FeatureGroup(), null);
        return;
      }

      if (result.error) {
        alert(`航线生成失败: ${result.error}`);
        setMissionStats(null);
        setExportData(null);
        onRouteCalculated(new L.FeatureGroup(), debugInfo);
        return;
      }

      // 清除旧的航线图层并绘制新的
      const newFlightPathLayer = new L.FeatureGroup();

      // result.waypoints 数组现在只包含实际任务航点
      const missionWaypoints = result.waypoints;

      if (missionWaypoints.length > 0) {
        // 绘制主任务航线 (实线)
        const missionPolyline = L.polyline(
          missionWaypoints.map((wp) => [wp.lat, wp.lng]),
          { color: "#007bff", weight: 2, opacity: 0.7 }
        );
        newFlightPathLayer.addLayer(missionPolyline);

        // 绘制从起飞点到第一个实际任务航点的连接线 (虚线)
        const firstMissionWaypoint = missionWaypoints[0];
        if (
          takeoffPoint &&
          (takeoffPoint.lat !== firstMissionWaypoint.lat ||
            takeoffPoint.lng !== firstMissionWaypoint.lng)
        ) {
          const initialConnectionLine = L.polyline(
            [
              [takeoffPoint.lat, takeoffPoint.lng],
              [firstMissionWaypoint.lat, firstMissionWaypoint.lng],
            ],
            { color: "#ff8c00", weight: 1, opacity: 0.8, dashArray: "5, 5" } // 橙色虚线
          );
          newFlightPathLayer.addLayer(initialConnectionLine);
        }

        // 绘制从最后一个实际任务航点到起飞点的返回连接线 (虚线)
        const lastMissionWaypoint =
          missionWaypoints[missionWaypoints.length - 1];
        if (
          takeoffPoint &&
          (lastMissionWaypoint.lat !== takeoffPoint.lat ||
            lastMissionWaypoint.lng !== takeoffPoint.lng)
        ) {
          const returnConnectionLine = L.polyline(
            [
              [lastMissionWaypoint.lat, lastMissionWaypoint.lng],
              [takeoffPoint.lat, takeoffPoint.lng],
            ],
            { color: "#8a2be2", weight: 1, opacity: 0.8, dashArray: "5, 5" } // 紫色虚线
          );
          newFlightPathLayer.addLayer(returnConnectionLine);
        }
      }

      // 绘制拍照点
      result.photoPoints.forEach((pp) => {
        const marker = L.circleMarker([pp.lat, pp.lng], {
          radius: 3,
          color: "red",
          fillColor: "#f03",
          fillOpacity: 0.5,
        });
        newFlightPathLayer.addLayer(marker);
      });

      onRouteCalculated(
        newFlightPathLayer,
        debugInfo,
        autoCalculatedAngleForDisplay
      ); // 传递自动计算的角度
      setMissionStats(result.stats);
      setExportData(result); // 保存结果，包含 missionParams
    } catch (error) {
      console.error("航线计算出错:", error);
      alert(`航线计算出错: ${(error as Error).message}`);
      setMissionStats(null);
      setExportData(null);
      onRouteCalculated(new L.FeatureGroup(), null);
    }
  };

  const handleExportRoute = async () => {
    // 检查是否有可导出的数据、已绘制多边形和任务参数
    if (
      !exportData ||
      exportData.waypoints.length === 0 ||
      !drawnPolygon ||
      !exportData.missionParams ||
      !takeoffPoint // 新增：检查起飞点
    ) {
      alert("没有可导出的航线或缺少必要的参数。");
      return;
    }

    const zip = new JSZip();
    const folderName = "waypoints"; // KMZ 根文件夹
    const wpmzFolderName = `${folderName}/wpmz`;
    const resFolderName = `${wpmzFolderName}/res`;
    const dsmFolderName = `${resFolderName}/dsm`; // DSM 文件目录

    // 创建文件夹结构
    zip.folder(wpmzFolderName);
    zip.folder(resFolderName);
    zip.folder(dsmFolderName);

    // 准备导出参数对象
    const exportParams: ExportParams = {
      missionType: missionType!, // missionType 在这里不会是 null
      mappingParams: missionType === "mapping" ? mappingParams : undefined,
      obliqueParams:
        missionType === "oblique" && obliqueParams
          ? {
              altitude: obliqueParams.altitude,
              gsd: obliqueParams.gsd,
              frontalOverlap: obliqueParams.frontalOverlap,
              sideOverlap: obliqueParams.sideOverlap,
              speed: obliqueParams.speed,
              angle: obliqueParams.angle,
              tiltAngle: obliqueParams.tiltAngle,
              buffer: obliqueParams.buffer,
              isSmartObliqueEnabled: obliqueParams.isSmartObliqueEnabled, // 新增
              droneModel: obliqueParams.droneModel, // 新增
            }
          : undefined,
      drawnPolygonGeoJSON: drawnPolygon.toGeoJSON() as Feature<Polygon>,
      takeoffPoint: takeoffPoint, // 新增：传递起飞点
      // 假设起飞点海拔为0，如果需要用户输入，这里需要修改
      takeoffPointAltitude: 0, // 默认0，可根据实际需求调整或从UI获取
    };

    try {
      // 生成 waylines.wpml 内容
      const waylinesWpmlContent = generateWaylinesWpml(
        exportData,
        exportParams
      );
      zip.file(`${wpmzFolderName}/waylines.wpml`, waylinesWpmlContent);
      console.log("Generated waylines.wpml:", waylinesWpmlContent);

      // 生成 template.kml 内容
      const templateKmlContent = generateTemplateKml(exportParams);
      zip.file(`${wpmzFolderName}/template.kml`, templateKmlContent);
      console.log("Generated template.kml:", templateKmlContent);

      // 生成 KMZ 文件
      const blob = await zip.generateAsync({ type: "blob" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = `${missionType}_flight_route.kmz`; // 下载文件名为 .kmz
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);

      alert("航线已导出为KMZ文件！");
    } catch (error) {
      console.error("KMZ导出失败:", error);
      alert(`KMZ导出失败: ${(error as Error).message}`);
    }
  };

  // 当关闭侧边栏时，清除统计信息和导出数据
  useEffect(() => {
    if (!isOpen) {
      setMissionStats(null);
      setExportData(null);
    }
  }, [isOpen]);

  return (
    <div
      className={`flex flex-col w-72 min-w-[300px] bg-[#2a2a2a] p-4 border-l border-[#3a3a3a] transition-transform duration-300 ease-in-out
        ${isOpen ? "translate-x-0" : "translate-x-full"}`}
    >
      <div className="flex justify-between items-center mb-5 pb-3 border-b border-[#3a3a3a]">
        <h3 className="text-lg font-semibold text-[#e0e0e0]">新建航线任务</h3>
        <button
          className="text-[#a0a0a0] text-xl cursor-pointer hover:text-[#e0e0e0]"
          onClick={onClose}
        >
          &times;
        </button>
      </div>
      <div className="flex-grow overflow-y-auto pr-2 -mr-2">
        <div className="text-center mb-4 pb-3 border-b border-[#3a3a3a] text-sm text-[#c0c0c0]">
          当前任务类型:{" "}
          <span className="font-bold text-[#007bff]">
            {missionType === "mapping"
              ? "建图航拍"
              : missionType === "oblique"
              ? "倾斜摄影"
              : "未选择"}
          </span>
        </div>

        {takeoffPoint && ( // 新增：显示起飞点坐标
          <div className="mb-4 text-sm text-[#c0c0c0]">
            起飞点:{" "}
            <span className="font-bold text-[#007bff]">
              {takeoffPoint.lat.toFixed(5)}, {takeoffPoint.lng.toFixed(5)}
            </span>
          </div>
        )}

        {missionType === "mapping" && (
          <MappingParams
            onParamsChange={setMappingParams}
            cameraParams={cameraParams}
            calculatedAutoAngle={calculatedAutoAngle} // 传递自动计算角度
          />
        )}
        {missionType === "oblique" && (
          <ObliqueParams
            onParamsChange={setObliqueParams}
            cameraParams={cameraParams}
            calculatedAutoAngle={calculatedAutoAngle} // 传递自动计算角度
          />
        )}

        <div className="param-group mb-4 mt-5 pt-3 border-t border-dashed border-[#4a4a4a]">
          <div className="flex items-center">
            <input
              type="checkbox"
              id="show-debug-layers-checkbox"
              checked={showDebugLayers}
              onChange={onToggleDebugLayers}
              className="mr-2 h-4 w-4 text-[#007bff] rounded focus:ring-[#007bff] bg-[#3a3a3a] border-[#4a4a4a]"
            />
            <label
              htmlFor="show-debug-layers-checkbox"
              className="text-sm text-[#c0c0c0]"
            >
              显示调试图层
            </label>
          </div>
        </div>

        <button
          className="w-full py-3 mt-5 rounded-md text-base cursor-pointer transition-colors duration-300
                bg-[#28a745] text-white hover:bg-[#218838] disabled:opacity-50 disabled:cursor-not-allowed"
          onClick={handleCalculateRoute}
          disabled={!drawnPolygon || !missionType}
        >
          开始计算
        </button>

        <MissionStatsComponent stats={missionStats} />

        {exportData && exportData.waypoints.length > 0 && (
          <button
            className="w-full py-3 mt-4 rounded-md text-base cursor-pointer transition-colors duration-300
                    bg-[#6c757d] text-white hover:bg-[#5a6268]"
            onClick={handleExportRoute}
          >
            导出航线 (KMZ)
          </button>
        )}
      </div>
    </div>
  );
};

export default RightSidebar;
